/**
 * Copyright 2023 Huawei Cloud Computing Technologies Co., Ltd.

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Asynchronous concurrent queue on promise
 */
export default class AsyncQueue {
    private queue = Promise.resolve();
    private resolve: (() => void) | null = null;
    private currentJobs = 0;

    /**
     * @param max max job number
     */
    // eslint-disable-next-line no-useless-constructor
    constructor(private max: number) {
        // empty
    }

    /**
     * Async do job. Jobs greater than max will be delay.
     * Notice: asyncDoJob does NOT await for the job, but for the asynchronous concurrent queue
     * @param job
     */
    public async asyncDoJob(job: () => Promise<void>) {
        if (this.currentJobs >= this.max) {
            await this.queue;
        }
        this.currentJobs++;
        if (this.currentJobs === this.max) {
            this.queue = new Promise((resolve) => {
                this.resolve = resolve;
            });
        }
        job().then(() => {
            this.currentJobs--;
            if (this.currentJobs < this.max) {
                this.resolve?.();
            }
        }); // No catch, error throws
    }
}
